package com.jse.api;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.SignatureException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.jse.Http;
import com.jse.Jse;
import com.jse.Lang;
import com.jse.Times;
import com.jse.json.JsonObject;
/**
 * 媒体视频API
 */
public class Media {
	// 账号AccessKey信息请填写(必选)
//    private static String access_key_id = "";
//    //账号AccessKey信息请填写(必选)
	private static String access_key_secret;
//    //STS临时授权方式访问时该参数为必选，使用主账号AccessKey和RAM子账号AccessKey不需要填写
//    private static String security_token = "";
	// 以下参数不需要修改
	private final static String VOD_DOMAIN = "http://vod.cn-shanghai.aliyuncs.com";
	
	private final static String HTTP_METHOD = "GET";
	private final static String HMAC_SHA1_ALGORITHM = "HmacSHA1";

	/**
	 * AccessKeyId AccesskeySecret
	 * 
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public static String api(Map<String,Object> param) {
		access_key_secret =(String)param.getOrDefault("AccesskeySecret",Jse.conf.getString("ali.secert"));
		param.put("AccessKeyId",param.getOrDefault("AccessKeyId",Jse.conf.getString("ali.key")));
		// 生成私有参数，不同API需要修改
		// 生成公共参数，不需要修改
		Map<String, String> publicParams = generatePublicParamters();
		// 生成OpenAPI地址，不需要修改
		// 发送HTTP GET 请求
//		LOG.debug("api url:%s",url);
		return generateOpenAPIURL(publicParams,new JsonObject(param).smap());
	}
	
	/**
	 * 获取url鉴权 (自动刷新auth_key)
	 * @param uri "http://v.iepsy.com/64f187cad5aa497cb4c1f68b6fee90ea/fbe2cf7f89364f09a30843ab5f1a6b80-23ed88f2a1a26984ec60a497bcc1d316.m3u8";
	 * @param key "iepsy123";
	 * @return
	 */
	public static String url(String uri,String key) {
		String host="";
		if(uri.contains("?")) {
			uri=uri.substring(0,uri.indexOf("?"));
		}
		if(uri.startsWith("http")) {
			host+=uri.substring(0,uri.indexOf("//")+2);
			uri=uri.substring(uri.indexOf("//")+2,uri.length());
		}
		host+=uri.substring(0,uri.indexOf("/"));
		String url=uri.substring(uri.indexOf("/"),uri.length());
		long timestamp=System.currentTimeMillis();
		String rand=Lang.uuid();
		String mh=Lang.md5(url+"-"+timestamp+"-"+rand+"-0-"+key);
		return host+url+"?auth_key="+timestamp+"-"+rand+"-0-"+mh;
	}

	/**
	 * 生成视频点播OpenAPI公共参数 不需要修改
	 * 
	 * @return
	 */
	private static Map<String, String> generatePublicParamters() {
		Map<String, String> publicParams = new HashMap<>();
		publicParams.put("Format", "JSON");
		publicParams.put("Version", "2017-03-21");
		publicParams.put("SignatureMethod", "HMAC-SHA1");
		publicParams.put("Timestamp", Times.utcTimestamp());
		publicParams.put("SignatureVersion", "1.0");
		publicParams.put("SignatureNonce", Lang.uuid());
		return publicParams;
	}
	
	

	/**
	 * 生成OpenAPI地址
	 * 
	 * @param privateParams
	 * @return
	 * @throws Exception
	 */
	private static String generateOpenAPIURL(Map<String, String> publicParams, Map<String, String> privateParams) {
		return generateURL(VOD_DOMAIN, HTTP_METHOD, publicParams, privateParams);
	}

	/**
	 * @param domain        请求地址
	 * @param httpMethod    HTTP请求方式GET，POST等
	 * @param publicParams  公共参数
	 * @param privateParams 接口的私有参数
	 * @return 最后的url
	 */
	private static String generateURL(String domain, String httpMethod, Map<String, String> publicParams,
			Map<String, String> privateParams) {
		List<String> allEncodeParams = getAllParams(publicParams, privateParams);
		String cqsString = getCQS(allEncodeParams);
//		System.out.println("CanonicalizedQueryString = " + cqsString);
		String stringToSign = httpMethod + "&" + percentEncode("/") + "&" + percentEncode(cqsString);
//		System.out.println("StringtoSign = " + stringToSign);
		String signature = hmacSHA1Signature(access_key_secret, stringToSign);
//		System.out.println("Signature = " + signature);
		return domain + "?" + cqsString + "&" + percentEncode("Signature") + "=" + percentEncode(signature);
	}

	private static List<String> getAllParams(Map<String, String> publicParams, Map<String, String> privateParams) {
		List<String> encodeParams = new ArrayList<String>();
		if (publicParams != null) {
			for (String key : publicParams.keySet()) {
				String value = publicParams.get(key);
				// 将参数和值都urlEncode一下。
				String encodeKey = percentEncode(key);
				String encodeVal = percentEncode(value);
				encodeParams.add(encodeKey + "=" + encodeVal);
			}
		}
		if (privateParams != null) {
			for (String key : privateParams.keySet()) {
				String value = privateParams.get(key);
				// 将参数和值都urlEncode一下。
				String encodeKey = percentEncode(key);
				String encodeVal = percentEncode(value);
				encodeParams.add(encodeKey + "=" + encodeVal);
			}
		}
		return encodeParams;
	}

	/**
	 * 参数urlEncode
	 *
	 * @param value
	 * @return
	 */
	private static String percentEncode(String value) {
		try {
			String urlEncodeOrignStr = URLEncoder.encode(value, "UTF-8");
			String plusReplaced = urlEncodeOrignStr.replace("+", "%20");
			String starReplaced = plusReplaced.replace("*", "%2A");
			String waveReplaced = starReplaced.replace("%7E", "~");
			return waveReplaced;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return value;
	}

	/**
	 * 获取CQS 的字符串
	 *
	 * @param allParams
	 * @return
	 */
	private static String getCQS(List<String> allParams) {
		Collections.sort(allParams,new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.compareTo(o2);
			}
		});
		String cqString = "";
		for (int i = 0; i < allParams.size(); i++) {
			cqString += allParams.get(i);
			if (i != allParams.size() - 1) {
				cqString += "&";
			}
		}
		return cqString;
	}

	private static String hmacSHA1Signature(String accessKeySecret, String stringtoSign) {
		try {
			String key = accessKeySecret + "&";
			try {
				SecretKeySpec signKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
				Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
				mac.init(signKey);
				byte[] rawHmac = mac.doFinal(stringtoSign.getBytes());
				// 按照Base64 编码规则把上面的 HMAC 值编码成字符串，即得到签名值（Signature）
				return Base64.getEncoder().encodeToString(rawHmac);
			} catch (Exception e) {
				throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
			}
		} catch (SignatureException e) {
			e.printStackTrace();
		}
		return "";
	}
	
	public static void main(String[] args) {
		JsonObject map=new JsonObject();
		map.put("AccessKeyId","LTAI8MDgUrXvLBpl");
		map.put("AccesskeySecret","OlEapJaG8KtKjqqPpLadX2b3zQ3p94");
		//GetVideoList
//		map.put("Status","Normal");
//		map.put("PageNo","1");
//		map.put("PageSize","1");
//		map.put("SortBy","CreationTime:Asc");
//		map.put("Action","GetVideoList");
		
//		map.put("Action","SearchMedia");
//		map.put("ScrollToken",new java.sql.Date(System.currentTimeMillis()).toString());//第一次不需要
		map.put("Fields","Title,CoverURL,Size,Duration,Status,Tags,CateName");
		map.put("SortBy","CreationTime:Asc");//CreationTime:Desc
		map.put("PageNo","1");
		map.put("PageSize","1");
		
//		map.put("Action","GetPlayInfo");//video
		map.put("VideoId","2caa8830667e71ee80580764a0fd0102");
//		map.put("Definition","FD");
		
		map.put("Action","GetMezzanineInfo");//audio
		
		String url=api(map);
		System.out.println(url);
		System.out.println(Http.get(url));
	}
}